/**
 * Copyright 2014 wasu.com
 *
 *
 * Create on 2014-9-16 下午2:23:20
 */
package xiaojian.toolkit.netty.handler.codec.http.response;

import io.netty.channel.Channel;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import xiaojian.toolkit.base.SendbackResponseHelper;
import xiaojian.toolkit.bean.json.JSONSignal;
import xiaojian.toolkit.bean.json.annotation.JSONMessage;
import xiaojian.toolkit.netty.util.NettyConstants;
import xiaojian.toolkit.util.ByteUtils;
import xiaojian.toolkit.util.Propertyable;

import com.alibaba.fastjson.JSON;

/**
 * 
 * 使用json编码bean，组装成HttpResponse发送出去。
 * 
 * @author <a href="mailto:caoxiaojian@wasu.com>xiaojian.cao</a>
 * 
 */
public abstract class AbstractJsonHttpSendbackResponseHelper implements
		SendbackResponseHelper {

	private static final Logger logger = LoggerFactory
			.getLogger(AbstractJsonHttpSendbackResponseHelper.class);

	private NettyHttpResponseBuilder httpResponseBuilder;

	private NettyHttpResponseSender httpResponseSender;

	// -- 是否允许跨域
	private boolean allowCrossRealm = false;

	/**
	 * @return the httpResponseBuilder
	 */
	public NettyHttpResponseBuilder getHttpResponseBuilder() {
		return httpResponseBuilder;
	}

	/**
	 * @param httpResponseBuilder
	 *            the httpResponseBuilder to set
	 */
	public void setHttpResponseBuilder(
			NettyHttpResponseBuilder httpResponseBuilder) {
		this.httpResponseBuilder = httpResponseBuilder;
	}

	/**
	 * @return the httpResponseSender
	 */
	public NettyHttpResponseSender getHttpResponseSender() {
		return httpResponseSender;
	}

	/**
	 * @param httpResponseSender
	 *            the httpResponseSender to set
	 */
	public void setHttpResponseSender(NettyHttpResponseSender httpResponseSender) {
		this.httpResponseSender = httpResponseSender;
	}

	public boolean isAllowCrossRealm() {
		return allowCrossRealm;
	}

	public void setAllowCrossRealm(boolean allowCrossRealm) {
		this.allowCrossRealm = allowCrossRealm;
	}

	protected abstract void beforeSend(HttpRequest httpRequest,
			FullHttpResponse response);

	/**
	 * @see stc.skymobi.netty.handler.codec.http.response.SendbackResponseHelper#makeAndSendback(java.lang.Object,
	 *      stc.skymobi.util.Propertyable)
	 */
	@Override
	public void makeAndSendback(Object responseBean, Propertyable requestBean) {

		if (logger.isDebugEnabled()) {
			logger.debug("sendback bean {} ", responseBean);
		}

		DefaultNettyResponseSource source = new DefaultNettyResponseSource();
		source.setStatus(HttpResponseStatus.OK);

		HttpRequest httpRequest = (HttpRequest) requestBean
				.getProperty(NettyConstants.HTTP_REQUEST);
		String contentType = httpRequest.headers().get(
				HttpHeaders.Names.CONTENT_TYPE);

		if (!NettyConstants.JSON_TYPE.equalsIgnoreCase(contentType)) {
			throw new RuntimeException("UnKnown Content-Type " + contentType);
		}

		source.setContentType(NettyConstants.JSON_TYPE);
		String jsonStr = JSON.toJSONString(responseBean);

		// -- 使用jsonp数据格式。
		if (requestBean instanceof JSONSignal) {
			JSONSignal jsonSinal = (JSONSignal) requestBean;
			if (jsonSinal.isJsonP()) {
				jsonStr = "upmCallback(" + jsonStr + ")";
			}
		}

		byte[] bytes = jsonStr.getBytes();

		if (logger.isDebugEnabled()) {
			logger.debug("sendback bean as Hex \r\n{} ",
					ByteUtils.bytesAsTLVHexString(bytes, 8096));
		}

		source.setContent(bytes);
		source.setContentLength(bytes.length);

		HttpResponse response = httpResponseBuilder.build(source);

		if (httpRequest != null) {
			String uuid = httpRequest.headers().get(NettyConstants.HEADER_UUID);
			if (uuid != null) {
				response.headers().set(NettyConstants.HEADER_UUID, uuid);
			}
			response.headers().set(HttpHeaders.Names.CONNECTION,
					httpRequest.headers().get(HttpHeaders.Names.CONNECTION));
		}

		// -- MsgCode
		JSONMessage jsonMessage = responseBean.getClass().getAnnotation(
				JSONMessage.class);
		if (jsonMessage != null) {
			response.headers().add(NettyConstants.HEADER_MESSAGE_CODE,
					jsonMessage.messageCode());
		}

		// -- 跨域的问题
		response.headers().add("Access-Control-Allow-Origin", "*");
		response.headers().add("Access-Control-Allow-Headers",
				"V,uuid,Msg,Content-Type");
		response.headers().add("Access-Control-Allow-Methods", "OPTIONS,POST,GET");

		beforeSend(httpRequest, (FullHttpResponse) response);

		httpResponseSender.sendResponse((Channel) requestBean
				.getProperty(NettyConstants.PROPERTY_CHANNEL), response);

	}
}
